<?php

defined('SYSPATH') or die('No direct script access.');

class Controller_Parse extends Controller {

	private static $array = array(
		'А' => array('А', 'A'),
		'В' => array('В', 'B'),
		'С' => array('С', 'C'),
		'Е' => array('Е', 'E'),
		'Н' => array('Н', 'H'),
		'К' => array('К', 'K'),
		'М' => array('М', 'M'),
		'О' => array('О', 'O'),
		'Р' => array('Р', 'P'),
		'Т' => array('Т', 'T'),
		'Х' => array('Х', 'X'),
		'а' => array('а', 'a'),
		'с' => array('с', 'c'),
		'е' => array('е', 'e'),
		'о' => array('о', 'o'),
		'р' => array('р', 'p'),
		'у' => array('у', 'y'),
		'х' => array('х', 'x'),
	);
	private static $array2 = array(
		'A' => 'А',
		'B' => 'В',
		'C' => 'С',
		'E' => 'Е',
		'H' => 'Н',
		'K' => 'К',
		'M' => 'М',
		'O' => 'О',
		'P' => 'Р',
		'T' => 'Т',
		'X' => 'Х',
		'a' => 'а',
		'c' => 'с',
		'e' => 'е',
		'o' => 'о',
		'p' => 'р',
		'y' => 'у',
		'x' => 'х',
	);

	public function after() {
//$this->response->body($this->_body	.	(Kohana::$profiling	?	View::factory('profiler/stats')	:	''));
//$this->response->body($this->_body);
		parent::after();
	}

	public function action_index() {
		$start = microtime(TRUE);
		$infile = '';
		for ($i = 0; $i < Arr::get($_POST, 'loop', 1000); $i++) {
			$output = $this->textPrepare(Arr::get($_POST, 'text', ''));
			$output = $this->parseTagsRecursive0($output);
			$output = $this->parseTagsRecursive1($output);
			$output = $this->parseTagsRecursive2($output);
			$output = $this->parseTagsRecursive1($output);
			$output = $this->parseTagsRecursive2($output);
			$output = str_replace('\n', "\n", $output);
			$output = str_replace('\t', "\t", $output);
			$infile .= $output . PHP_EOL . PHP_EOL;
			$md5 = md5($output);
			unset($output);

			if (!empty($hashes[$md5])) {
				$hashes[$md5] ++;
			}
			else {
				$hashes[$md5] = 1;
			}
		}
		if (Arr::get($_POST, 'infile', 0)) {
			$this->response->body($infile);
			$this->response->send_file(TRUE, 'parser_' . date('Y.m.d_H-i-s') . '_LOOP' . Arr::get($_POST, 'loop', 1000) . '.txt');
		}
		else {
			$infile = preg_replace('#([a-z])#si', "<b style='color:red'>\\1</b>", $infile);
			$time = microtime(TRUE) - $start;
			$this->response->body(View::factory($this->request->controller(), array('time' => $time, 'hashes' => $hashes, 'output' => $infile, 'text' => Arr::get($_POST, 'text', ''), 'loop' => Arr::get($_POST, 'loop', 1000), 'infile' => Arr::get($_POST, 'infile', 0))));
		}
	}

	public function action_demorph() {
		$start = microtime(TRUE);
		$text = Arr::get($_POST, 'text', '');
		$textdemorph = '';
		if (!empty($text)) {
			$textdemorph = strtr($text, self::$array2);
		}
		$time = microtime(TRUE) - $start;
		$this->response->body(View::factory($this->request->controller() . '_' . $this->request->action(), array('time' => $time, 'textdemorph' => $textdemorph, 'text' => $text)));
	}

	private function parseTagsRecursive0(&$input) {
		$regex = '`##(.*?)##`si';
		if (is_array($input)) {
			$chars = UTF8::str_split($input[1]);
//print_r(self::$array);
			foreach ($chars as &$char) {
				if (!empty(self::$array[$char])) {
					$char = self::$array[$char][array_rand(self::$array[$char])];
				}
			}
			$input = implode('', $chars);
		}
		return preg_replace_callback($regex, array($this, 'parseTagsRecursive0'), $input);
	}

	private function parseTagsRecursive1(&$input) {
		$regex = '#{([^{}\[\]]+)}#si';
		if (is_array($input)) {
			$arr = explode('|', $input[1]);
			$input = $arr[array_rand($arr)];
		}
		return preg_replace_callback($regex, array($this, 'parseTagsRecursive1'), $input);
	}

	private function parseTagsRecursive2(&$input) {
		$regex = '#\[([^\[\]{}]+)\]#si';
		if (is_array($input)) {
			$arr = explode('|', $input[1]);
			$implode = '';
			if (preg_match('#\+(.*?)\+#si', $arr[0], $m)) {
				$arr[0] = str_replace($m[0], '', $arr[0]);
				$implode = $m[1];
			}
			shuffle($arr);
			$input = implode($implode, $arr);
		}
		return preg_replace_callback($regex, array($this, 'parseTagsRecursive2'), $input);
	}

	private function textPrepare($input) {
		if (preg_match_all('#{//s(\d+)//(.*?)}#si', $input, $m)) {
			foreach ($m[2] as $id => &$str) {
				$arr = explode('|', $str);
				$r[1][$id] = $arr[array_rand($arr)];
				$r[0][$id] = '//s' . $m[1][$id] . '//';
				$r[2][$id] = $m[0][$id];
			}
			if (!empty($r)) {
				$input = str_replace($r[2], $r[1], $input);
				$input = str_replace($r[0], $r[1], $input);
			}
		}
		return $input;
	}

	public function action_ip() {
		$net = array(
			'188.93.57.192/26',	 //188.93.57.192	- 188.93.57.255
			'188.93.57.0/26',	 //188.93.57.0		- 188.93.57.63
			'188.93.57.82',
			'217.69.134.98',
			'217.69.143.37',
			'217.69.143.38',
			'217.69.143.39',
		);
		if ($this->ip_match('188.93.57.214',$net)){
			echo 'match';
		}
		else {
			echo 'not match';
		}
	}

	/*
	 * Проверка принадлежности IP-адреса массиву подсетей.
	 * Массив можно задавать разными способами:
	 * $net = array();
	 * $net[] = "82.208.77.243/28";
	 * $net[] = "82.208.77.243-85.95.168.249";
	 * $net[] = "94.240.64.1-92.240.127.254";
	 * $net[] = "92.240.128.2";
	 * В диапазоне производится проверка отношения начальной и конечной точки.
	 */

	private function ip_match($addr, $cidrs) {
		if (!is_array($cidrs))
			$cidrs = array($cidrs);
		foreach ($cidrs as $cidr) {
			if (strpos($cidr, "/")) { // Для записей типа 82.208.77.243/32
				list($ip, $mask) = explode("/", $cidr, 2);
				if (strpos(".", $mask))
					$mask = 0xffffffff & ip2long($mask);
				else
					$mask = 0xffffffff << 32 - (int) $mask;
				if ((ip2long($addr) & $mask) == (ip2long($ip) & $mask))
					return true;
			}
			elseif (strpos($cidr, "-")) { // Для записей типа 82.208.77.243-85.95.168.249
				list($ip_1, $ip_2) = explode("-", $cidr, 2);
				if (((ip2long($ip_2) > ip2long($ip_1)) && (((ip2long($addr) - ip2long($ip_1)) >= 0) && (( ip2long($ip_2) - ip2long($addr)) >= 0))) || ((ip2long($ip_2) < ip2long($ip_1)) && (((ip2long($addr) - ip2long($ip_1)) <= 0) && ((ip2long($ip_2) - ip2long($addr)) <= 0))) || ((ip2long($ip_1) == ip2long($ip_2)) && (ip2long($ip_1) == ip2long($addr))))
					return true;
			}
			else if ($addr === $cidr)
				return true; // Для одиночных IP
		}
		return false;
	}

}

// End Parse
